package io.shuttle.mbe.api

import io.shuttle.mbe.api.annotation.ChromeMinVersion
import io.shuttle.mbe.api.types.Value1Function
import io.shuttle.mbe.api.types.Value2Function
import io.shuttle.mbe.api.types.Value3Function
import io.shuttle.mbe.api.types.VoidFunction
import io.shuttle.mbe.core.JSObject
import io.shuttle.mbe.core.Promise

////////////////////
// Debugger
////////////////////
/**
 * The `Browser.debugger` API serves as an alternate transport for Chrome's remote debugging protocol. Use `Browser.debugger` to attach to one or more tabs to instrument network interaction, debug JavaScript, mutate the DOM and CSS, and more. Use the {@link Debuggee} `tabId` to target tabs with `sendCommand` and route events by `tabId` from `onEvent` callbacks.
 *
 * Permissions: "debugger"
 */
interface Debugger {
    // Attaches debugger to the given target.
    @ChromeMinVersion(96)
     fun attach(
        // Debugging target to which you want to attach.
        target: Debuggee,
        // Required debugging protocol version ("0.1").
        // One can only attach to the debuggee with matching major version and greater
        // or equal minor version. List of the protocol versions can be obtained here.
        requiredVersion: String,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Detaches debugger from the given target.
    @ChromeMinVersion(96)
     fun detach(
        // Debugging target from which you want to detach.
        target: Debuggee,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Returns the list of available debug targets.
    @ChromeMinVersion(96)
     fun getTargets(
        callback: Value1Function<List<TargetInfo>>? = null,
    ): Promise<List<TargetInfo>>

    // Sends given command to the debugging target.
    // @return JSON object with the response. Structure of the response varies depending on the method name
    // and is defined by the 'returns' attribute of the command description in the remote debugging protocol.
    @ChromeMinVersion(96)
     fun sendCommand(
        // Debugging target to which you want to send the command.
        target: DebuggerSession,
        // Method name. Should be one of the methods defined by the remote debugging protocol.
        method: String,
        // JSON object with request parameters. This object must conform to the remote debugging params scheme for given method.
        commandParams: JSObject,
        callback: Value1Function<JSObject?>? = null,
    ): Promise<JSObject?>

    // Fired when browser terminates debugging session for the tab.
    // This happens when either the tab is being closed or Chrome DevTools is being invoked for the attached tab.
     val onDetach: Events.Event<Value2Function<Debuggee, DetachReason>>

    // Fired whenever debugging target issues instrumentation event.
     val onEvent: Events.Event<Value3Function<DebuggerSession, String, JSObject?>>

    // Debuggee identifier. Either tabId, extensionId or targetId must be specified
    data class Debuggee(
        // The id of the extension which you intend to debug. Attaching to an extension background page
        // is only possible when the --silent-debugger-extension-api command-line switch is used.
        var extensionId: String?,
        // The id of the tab which you intend to debug.
        var tabId: String?,
        // The opaque id of the debug target.
        var targetId: String?,
    )

    // Debugger session identifier. One of tabId, extensionId or targetId must be specified.
    // Additionally, an optional sessionId can be provided.
    // If sessionId is specified for arguments sent from onEvent,
    // it means the event is coming from a child protocol session within the root debuggee session.
    // If sessionId is specified when passed to sendCommand,
    // it targets a child protocol session within the root debuggee session.
    @ChromeMinVersion(125)
    data class DebuggerSession(
        // The id of the extension which you intend to debug. Attaching to an extension background page
        // is only possible when the --silent-debugger-extension-api command-line switch is used.
        var extensionId: String?,
        // The opaque id of the Chrome DevTools Protocol session.
        // Identifies a child session within the root session identified by tabId, extensionId or targetId.
        var sessionId: String?,
        // The id of the tab which you intend to debug.
        var tabId: String?,
        // The opaque id of the debug target.
        var targetId: String?,
    )

    // Connection termination reason.
    @ChromeMinVersion(44)
    enum class DetachReason {
        target_closed,
        canceled_by_user
    }

    // Debug target information
    data class TargetInfo(
        // True if debugger is already attached.
        var attached: Boolean,
        // The extension id, defined if type = 'background_page'.
        var extensionId: String?,
        // Target favicon URL.
        var faviconUrl: String?,
        // Target id.
        var id: String,
        // The tab id, defined if type == 'page'.
        var tabId: Number?,
        // Target page title.
        var title: String,
        // Target type.
        var type: TargetInfoType,
        // Target URL.
        var url: String,
    )

    @ChromeMinVersion(44)
    enum class TargetInfoType {
        page,
        background_page,
        worker,
        other
    }

}